home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-05 / pdclk139.zip / PING.ASM < prev    next >
Assembly Source File  |  1992-05-17  |  16KB  |  748 lines

  1. ;        ping.asm
  2. ;========================================================================
  3.  
  4. ; Copyright (C) 1991 by Jan.Engvald@ldc.lu.se, see file COPYING.
  5.  
  6. MsgEchoHead    db    CR, LF, "Ping with packet size "
  7. MsgEchoSweep    db    " "
  8. MsgEchoSize    db    "0    and interval"
  9. MsgEchoMs    db    "     0 ms to "
  10. MsgEchoTarget    db    "1.2.3.4        :", CR, LF, LF
  11.         db    "───────── Packets ──────── ║ ────── Delay ms ────── ║   Packet  ║ Load ║  Time ", CR, LF
  12.         db    "transmit  receive     diff ║ this   min   avg   max ║    loss   ║ kb/s ║     s ", CR, LF, "$$"
  13. MsgEcho        db    "       0        0        0      0     0     0     0     0.0000 %     0       0 ", CR, '$'
  14.  
  15. MsgSerrTbl    dw    offset MsgSerrUnr
  16.         dw    offset MsgSerrObuf
  17.         dw    offset MsgSerrNoarp
  18.         dw    offset MsgSerrTimout
  19.         dw    offset MsgSerrNotraf
  20. SERRTABLEN      equ     $-MsgSerrTbl
  21.         dw    offset MsgSerrUnimpl
  22.  
  23. MsgSerrUnr    db    LF, "Host or net unreachable", CR, LF, '$'
  24. MsgSerrObuf    db    LF, "Temporary out of buffers", CR, LF, '$'
  25. MsgSerrNoarp    db    LF, "Got no ARP reply", CR, LF, '$'
  26. MsgSerrTimout    db    LF, "Timeout", CR, LF, '$'
  27. MsgSerrNotraf    db    LF, "Received no traffic from destination", CR, LF, '$'
  28.  
  29. MsgSerrUnimpl    db    LF, "Send Error.", CR, LF, '$'
  30.         even
  31. EchoTarget    dw    0, 0            ; echo argument values
  32. EchoSize    dw    30
  33. EchoInterval    dw    256
  34. EchoData    dw    101h
  35. EchoDataIncW    dw    1
  36.  
  37. EchoStart    dw    0, 0, 0            ; echo variables
  38. EchoNext    dw    0
  39. EchoLastDispl    dw    0
  40. EchoLastHi    dw       0
  41. EchoMaxSize    dw    1500
  42. EchoAvgSum    dw    0, 0
  43. EchoFudge    dw    0
  44. EchoLoad    dw    0, 0
  45. EchoDrop    dw    0
  46. PingRowCnt    dw    17
  47.  
  48. EchoTx32    dw    0, 0            ; echo display variables
  49. EchoRx32    dw    0, 0
  50. EchoDif     dw    0, 0
  51. EchoThis    dw    0
  52. EchoMin     dw    0ffffh
  53. EchoAvg     dw    0
  54. EchoMax     dw    0
  55. EchoLoss    dw    0, 0
  56. EchoElapsed    dw    0, 0
  57.  
  58. k27        dw    27
  59. k55        dw    55
  60. k100        dw    100
  61.  
  62.  
  63. ;************************************************************************
  64. ;*        EchoAwhile
  65. ;************************************************************************
  66.  
  67. MsgCalling    db    "Calling nameserver(s)... $"
  68. MsgNameRep    db    "got reply in "
  69. MsgNameRepTim    db    "     ms.", CR, LF, '$'
  70. MsgBadName    db    LF, "Bad hostname.$"
  71.  
  72. EchoAwhile    proc    near
  73.                 cmp     EchoTarget,0            ; want to ping someone?
  74.                 jne     EchoYes
  75.                 ret
  76.   EchoYes:
  77.         call    InitTimer        ; prepare millisecond timing
  78.         call    HardwareTicks
  79.  
  80.         mov    EchoStart,si        ; note start ticks
  81.         mov    EchoStart+2,dx
  82.         mov    EchoStart+4,ax
  83.  
  84.         call    DblShr10
  85.         mov    EchoNext,ax
  86.  
  87.                 cmp     EchoTarget,127          ; dns lookup to do?
  88.                 jne     EchoIpAddr
  89.  
  90.         mov    dx,offset MsgCalling
  91.         mov    ah,9
  92.         int    21h
  93.  
  94.         mov    dx,2345h        ; ping udp src port
  95.         xor    ax,ax            ; NsId
  96.         mov    si,offset EchoNameBuf    ; Ns question string
  97.  
  98.         call    NsResolve        ; call nameserver(s)
  99.  
  100.         call    HardwareTicks        ; response time
  101.         sub    ax,EchoStart+4
  102.         sbb    dx,EchoStart+2
  103.         div    kTimerScale
  104.         mov    di,offset MsgNameRepTim
  105.         mov    PutNumFiller,' '
  106.         mov    PutMinDigits,4
  107.         call    PutNum
  108.  
  109.         mov    dx,offset MsgNameRep    ; display it.
  110.         mov    ah,9
  111.         int    21h
  112.  
  113.                 cmp     EchoTarget,127          ; name resolved?
  114.                 jne     EchoIpAddr
  115.  
  116.         mov    dx,offset MsgBadName
  117.         mov    ah,9
  118.         int    21h
  119.   EchoRet:
  120.                 ret
  121.  
  122.   EchoIpAddr:
  123.         test    ArgFlags,MAKE_TABLE
  124.         jz    EchoNotTbl
  125.         or    GenFlags,TBL_READY
  126.   EchoNotTbl:
  127.         mov    di,offset EchoSizeVec
  128.         mov    cx,(EchoSizeEnd-EchoSizeVec)/2
  129.         xor    ax,ax
  130.         rep    stosw
  131.  
  132.         test    ArgFlags,TERM_WAIT
  133.         jnz    EchoAsIs
  134.         cmp    EchoInterval,128
  135.         jge    EchoAsIs
  136.         mov    EchoInterval,128
  137.   EchoAsIs:
  138.         call    BufAlloc        ; get a send buf
  139.         jz    EchoRet
  140.  
  141.         call    MakeSendDescr
  142. ;*test        mov    [bx].dTickTimeout,8*18
  143.         mov    [di].uIcmpTypeCode,8    ; type = echo request
  144.         mov    cx,(1500-IPHDRLEN-ICMPHDRLEN)/2
  145.         add    di,ICMPHDRLEN
  146.         mov    ax,EchoData
  147.   EchoFillLoop:
  148.         stosw
  149.         add    ax,EchoDataIncW
  150.         loop    EchoFillLoop
  151.   EchoFillEnd:
  152.         mov    si,offset EchoTarget-iIpSrc
  153.         call    SwitchIpdstB        ; set IP destination
  154.  
  155.         mov    si,offset EchoTarget
  156.         mov    di,offset MsgEchoTarget
  157.         call    PutIpNum        ; tell who we are pinging
  158.  
  159.         mov    cx,EchoSize
  160.         or    cx,cx
  161.         jns    EchoSizePos
  162.         neg    cx
  163.         mov    MsgEchoSweep,'<'
  164.   EchoSizePos:
  165.         sub    cx,IPHDRLEN+ICMPHDRLEN
  166.         cmp    cx,GIANT-HWHDRLEN-IPHDRLEN-ICMPHDRLEN
  167.         jbe    EchoOkSize
  168.         mov    cx,30-IPHDRLEN-ICMPHDRLEN
  169.   EchoOkSize:
  170.         mov    ax,cx
  171.         add    ax,IPHDRLEN+ICMPHDRLEN
  172.         mov    EchoSize,cx
  173.         mov    EchoMaxSize,cx
  174.  
  175.         mov    di,offset MsgEchoSize
  176.         mov    PutMinDigits,1
  177.         call    PutNum            ;   and the packet size used
  178.  
  179.         mov    ax,EchoInterval
  180.         mov    di,offset MsgEchoMs
  181.         mov    PutMinDigits,6
  182.         mov    PutNumFiller,' '
  183.         call    PutNum            ;   and interval in ms
  184.  
  185.         mov    dx,offset MsgEchoHead
  186.         mov    ah,9
  187.         int    21h            ; display it
  188.   EchoLoop0:
  189.         nop                ; (just to separate the loops)
  190.   EchoLoop:
  191.         call    Something2Do        ; process other things
  192.         jnz    EchoLoop        ; maybe more to do
  193.  
  194.         call    EchoDisplay        ; show current values
  195.  
  196.         call    AnyKey            ; first key stops sending
  197.         jz    EchoNoKey
  198. if 0
  199.         cmp    al,'y' and 01fh        ; ignore most control keys
  200.         jbe    EchoNoKey
  201. endif
  202.         jmp    EchoEnd
  203.   EchoNoKey:
  204.         cmp    FreeBufs.lBufsAvail,3*NBUFS/4
  205.         jle    EchoLoop        ; prevent buffer starving
  206.  
  207.         call    HardwareTicks
  208.         call    DblShr10
  209.         mov    dx,ax
  210.         sub    ax,EchoNext        ; time to send next echo pkt?
  211.         js    EchoLoop0
  212.  
  213.         add    dx,EchoInterval
  214.         mov    EchoNext,dx        ; next send time
  215.  
  216.         add    EchoTx32+2,1        ; increment send counters
  217.         adc    EchoTx32,0
  218.         mov    EchoFudge,1
  219.  
  220.         mov    cx,EchoSize        ; compute packet size
  221.         cmp    MsgEchoSweep,'<'
  222.         jne    EchoFillFixed
  223.         inc    cx
  224.         cmp    cx,EchoMaxSize
  225.         jbe    EchoFillSize
  226.         mov    cx,28-IPHDRLEN-ICMPHDRLEN
  227.   EchoFillSize:
  228.         mov    EchoSize,cx
  229.   EchoFillFixed:
  230.         add    cx,ICMPHDRLEN        ; IP data length
  231.  
  232.         mov    ax,cx
  233.         add    ax,IPHDRLEN+14+8+4+12    ; preamble, crc, intergap ...
  234.         cli
  235.         add    EchoLoad+2,ax
  236.         adc    EchoLoad,0
  237.         sti
  238.  
  239.         mov    di,cx
  240.         shl    di,1
  241.         inc    word ptr EchoSizeVec[di]
  242.  
  243.         call    HardwareTicks        ; put timestamp
  244.         mov    di,[bx].dPtrUdp
  245.         mov    [di].uIcmpData,ax
  246.         mov    [di].uIcmpData+2,dx
  247.  
  248.         call    SendIcmpPkt        ; send echo pkt
  249.         jnz    EchoErr         ; any errors?
  250.         jmp    EchoLoop
  251.  
  252.   EchoErr:
  253.         xor    ch,ch
  254.         cmp    cl,SERRTABLEN
  255.         jb    EchoErrExist
  256.         mov    cl,SERRTABLEN
  257.   EchoErrExist:
  258.         mov    si,cx
  259.         mov    dx,MsgSerrTbl[si]
  260.         mov    ah,9
  261.         int    21h            ; display send error
  262.   EchoEnd:
  263.         call    BufRelease        ; release send buffer
  264.         mov    EchoFudge,0
  265.         or    ArgFlags,TERM_WAIT
  266.         ret
  267. EchoAwhile    endp
  268.  
  269.  
  270.  
  271. if DEBUG
  272.   TstBufLinks    proc    near
  273.         ja    TstErrEI
  274.         mov    si,di
  275.         inc    cx
  276.     TstLinkLoop:
  277.         mov    di,[di].dNext
  278.         mov    si,[si].dPrev
  279.         loop    TstLinkLoop
  280.         cmp    si,di
  281.         jne    TstErrEI
  282.         ret
  283.   TstBufLinks    endp
  284.  
  285.   TstErrEI:
  286.         PopfEI
  287.   TstErr:
  288.         push    bx
  289.         mov    bx,'>-'
  290.         push    bx
  291.         push    bx
  292.         call    terminate
  293. endif ; DEBUG
  294.  
  295.  
  296.  
  297. ;************************************************************************
  298. ;*        EchoDisplay
  299. ;************************************************************************
  300.  
  301.  
  302. EchoDisplay    proc    near
  303. if DEBUG
  304.         push    bx
  305.         mov    al,'s'-'0'
  306.         cmp    word ptr phd_dioa,0    ; stack overflowed?
  307.         jne    TstErr
  308.  
  309.         mov    al,'t'-'0'
  310.         cmp    word ptr StackLow,0    ; stack overflowed?
  311.         jne    TstErr
  312.  
  313.         mov    al,'i'-'0'
  314.         test    GenFlags,DBGINTERR    ; any interrupt debug errs?
  315.         jnz    TstErr
  316.  
  317.         mov    cx,NBUFS        ; any buffers damaged?
  318.         mov    bx,offset BufStart
  319.         mov    al,'u'-'0'
  320.   BufTestLoop:
  321.                 cmp     [bx].dHomeList,offset FreeBufs
  322.         jne    TstErr
  323.         add    bx,BUFSIZE
  324.         loop    BufTestLoop
  325.  
  326.         PushfDI
  327.         mov    di,offset FreeBufs
  328.         mov    cx,[di].lBufsAvail
  329.         cmp    cx,NBUFS
  330.         call    TstBufLinks
  331.         cmp    di,offset FreeBufs
  332.         jne    TstErrEI
  333.         PopfEI
  334.  
  335.                 mov     cx,NBUFSMALL
  336.         mov    al,'v'-'0'
  337.   TstSmlLoop:
  338.                 cmp     [bx].dHomeList,offset FreeSmal
  339.         jne    TstErr
  340.                 add     bx,BUFSIZESML
  341.                 loop    TstSmlLoop
  342.  
  343.         PushfDI
  344.         mov    di,offset FreeSmal
  345.         mov    cx,[di].lBufsAvail
  346.         cmp    cx,NBUFSMALL
  347.         call    TstBufLinks
  348.         cmp    di,offset FreeSmal
  349.         jne    TstErrEI
  350.         PopfEI
  351.         pop    bx
  352. endif ; DEBUG
  353.         cmp    EchoTarget,0        ; are we pinging?
  354.         je    EchoDispRet
  355.  
  356.         call    CurrentTicks
  357.         shr    cx,1
  358.         shr    cx,1
  359.         mov    ax,EchoLastDispl
  360.         shr    ax,1
  361.         shr    ax,1
  362.         cmp    ax,cx            ; time to update display?
  363.         jne    EchoDispNow
  364.   EchoDispRet:
  365.         ret
  366.  
  367.   EchoDispNow:
  368.         push    bx
  369.  
  370.         cli
  371.         mov    dx,EchoAvgSum
  372.         mov    ax,EchoAvgSum+2
  373.         mov    cx,EchoRx32
  374.         mov    bx,EchoRx32+2
  375.         sti
  376.         call    AdjTo16Bits
  377.         or    bx,bx            ; avoid div by zero
  378.         jz    EchoSkipAvg
  379.  
  380.         div    bx
  381.         mov    EchoAvg,ax        ; average delay
  382.   EchoSkipAvg:
  383.  
  384.         mov    dx,EchoTx32        ; compute difference tx - rx
  385.         mov    ax,EchoTx32+2
  386.         sub    ax,EchoFudge        ;   subtract one if just
  387.         sbb    dx,0            ;   sent a pkt
  388.         push    ax
  389.         push    dx
  390.         cli
  391.         sub    ax,EchoRx32+2
  392.         sbb    dx,EchoRx32
  393.         sti
  394.         jns    EchoDifPos        ; use abs(tx-rx)
  395.         not    ax
  396.         not    dx
  397.         add    ax,1
  398.         adc    dx,0
  399.   EchoDifPos:
  400.         mov    Echodif,dx
  401.         mov    Echodif+2,ax
  402.  
  403.         mov    cl,2            ; compute packet loss
  404.         call    DblShl            ;   multiply by 100
  405.         mov    si,dx
  406.         mov    bx,ax
  407.         mov    cl,3
  408.         call    DblShl
  409.         add    bx,ax
  410.         adc    si,dx
  411.         shl    ax,1
  412.         rcl    dx,1
  413.         add    ax,bx
  414.         adc    dx,si
  415.  
  416.         pop    cx
  417.         pop    bx
  418.  
  419.         call    AdjTo16Bits
  420.         or    bx,bx            ; avoid div by zero
  421.         jz    EchoSkipLoss
  422.  
  423.         div    bx
  424.         mov    EchoLoss,ax
  425.  
  426.         mov    ax,dx            ;   fractional loss
  427.         mul    k10000
  428.         div    bx
  429.         mov    EchoLoss+2,ax
  430.   EchoSkipLoss:
  431.         push    cs            ; edit echo values
  432.         pop    es
  433.  
  434.         mov    di,offset MsgEcho-1
  435.         mov    si,offset EchoTx32
  436.         mov    PutNumFiller,' '
  437.         mov    PutMinDigits,9
  438.         mov    cx,3
  439.         call    PutBigNums        ; tx and rx and diff
  440.  
  441.         mov    PutMinDigits,6
  442.         inc    di
  443.         mov    cx,5
  444.   EchoDispLoop:
  445.         push    cx
  446.         mov    cl,1
  447.         call    PutNums            ; delays and loss
  448.         pop    cx
  449.         loop    EchoDispLoop
  450.  
  451.         mov    PutNumFiller,'0'
  452.         inc    di
  453.         mov    cl,1
  454.         call    PutNumsD4        ; .0000%
  455.  
  456.         cli
  457.         mov    ax,EchoLoad+2
  458.         mov    dx,EchoLoad
  459.         mov    EchoLoad+2,0
  460.         mov    EchoLoad,0
  461.         sti
  462.         div    k27            ; assumes clr every 2nd tick
  463.         add    di,4
  464.         mov    PutNumFiller,' '
  465.         call    PutNum            ; load kb/s
  466.  
  467.         call    HardwareTicks        ; compute elapsed time
  468.         mov    ax,dx
  469.         mov    dx,si
  470.         cmp    dx,EchoLastHi
  471.         jae    EchoLastGrows
  472.  
  473.         mov    bx,EchoLastDispl
  474.         mov    cx,EchoLastHi
  475.         sub    EchoStart+2,bx
  476.         sbb    EchoStart,cx
  477.   EchoLastGrows:
  478.         mov    EchoLastDispl,ax
  479.         mov    EchoLastHi,dx
  480.         sub    ax,EchoStart+2
  481.         sbb    dx,EchoStart
  482.         mov    cl,4            ; divide # of ticks by 18.2
  483.         call    DblShr
  484.         mov    EchoElapsed+2,ax
  485.         mov    EchoElapsed,dx
  486.         mov    cl,3
  487.         call    DblShr
  488.         sub    EchoElapsed+2,ax
  489.         sbb    EchoElapsed,dx
  490.         mov    cl,5
  491.         call    DblShr
  492.         add    ax,EchoElapsed+2
  493.         adc    dx,EchoElapsed
  494.         mov    PutNumFiller,' '
  495.         mov    PutMinDigits,8
  496.         call    PutBigNum        ; elapsed time
  497. if DEBUG
  498.         mov    dx,280h+10h        ; assume WD card at IO 280h
  499.         xor    ax,ax
  500.         xor    cx,cx
  501.         cli
  502.         out    dx,al            ; set page 0
  503.         call    IoDelay
  504.         add    dx,0dh
  505.         in    al,dx            ; readandclear frame err ctr
  506.         add    cx,ax
  507.         inc    dx
  508.         in    al,dx            ; readnadclear bad CRC ctr
  509.         add    cx,ax
  510.         inc    dx
  511.         in    al,dx            ; readandclear lost frames ctr
  512.         sti
  513.         add    cx,ax
  514.         add    EchoDrop,cx        ; add out of bufs ctr
  515.         mov    di,offset MsgEcho+18    ; place before diff
  516.         mov    ax,EchoDrop
  517.         mov    PutMinDigits,1
  518.         call    PutNum            ; show dropped packets
  519. endif ; DEBUG
  520.  
  521.         mov    dx,offset MsgEcho    ; display echo values
  522.         mov    ah,9
  523.         int    21h
  524.  
  525.         pop    bx
  526.         ret
  527. EchoDisplay    endp
  528.  
  529.  
  530.  
  531. ;************************************************************************
  532. ;*        AdjTo16Bits
  533. ;************************************************************************
  534.  
  535. AdjTo16Bits    proc    near
  536.   AdjTest:
  537.         or    cx,cx            ; fits in 16 bits?
  538.         jnz    Adjust
  539.         or    dx,dx
  540.         jnz    Adjust
  541.         ret
  542.   Adjust:
  543.         shr    dx,1            ; shift 32 bits right
  544.         rcr    ax,1
  545.         shr    cx,1
  546.         rcr    bx,1
  547.         jmp    short AdjTest
  548. AdjTo16Bits    endp
  549.  
  550.  
  551.  
  552. ;************************************************************************
  553. ;*        DblShr
  554. ;************************************************************************
  555.  
  556. DblShr10     proc    near
  557.         mov    cl,10
  558. DblShr:
  559.         xor    ch,ch
  560.   DblShrNext:
  561.         shr    dx,1            ; shift 32 bits right
  562.         rcr    ax,1
  563.         loop    DblShrNext
  564.         ret
  565. DblShr10     endp
  566.  
  567.  
  568.  
  569. ;************************************************************************
  570. ;*        DblShl
  571. ;************************************************************************
  572.  
  573. DblShl        proc    near
  574.         xor    ch,ch
  575.   DblShlNext:
  576.         shl    ax,1            ; shift 32 bits left
  577.         rcl    dx,1
  578.         loop    DblShlNext
  579.         ret
  580. DblShl        endp
  581.  
  582.  
  583.  
  584. ;************************************************************************
  585. ;*        EchoCalc
  586. ;************************************************************************
  587.  
  588.         even
  589. kTimerScale    dw    TimerResolution
  590.  
  591. EchoCalc    proc    near
  592.  
  593.         add    EchoRx32+2,1        ; increment receive counters
  594.         adc    EchoRx32,0
  595.         mov    EchoFudge,0
  596.  
  597.         mov    ax,[bx].dPktLen        ; IP data length
  598.         mov    di,ax
  599.         add    ax,IPHDRLEN+14+8+4+12    ; preamble, crc, intergap
  600.         add    EchoLoad+2,ax
  601.         adc    EchoLoad,0
  602.  
  603.         shl    di,1
  604.         dec    word ptr EchoSizeVec[di]
  605.  
  606.         call    HardwareTicks        ; compute delay
  607.         mov    di,[bx].dPtrUdp
  608.         sub    ax,[di].uIcmpData
  609.         sbb    dx,[di].uIcmpData+2
  610.         js    EchoCalcRet
  611.         div    kTimerScale
  612.         mov    EchoThis,ax        ; delay for this packet
  613.  
  614.         add    EchoAvgSum+2,ax
  615.         adc    EchoAvgSum,0
  616.  
  617.         cmp    ax,EchoMin
  618.         jb    EchoSetMin
  619.   EchoChkMax:
  620.         cmp    ax,EchoMax
  621.         ja    EchoSetMax
  622.   EchoCalcRet:
  623.         ret
  624.  
  625.   EchoSetMin:
  626.         mov    EchoMin,ax        ; minimum delay
  627.         jmp    short EchoChkMax
  628.   EchoSetMax:
  629.         mov    EchoMax,ax        ; maximum delay
  630.         ret
  631. EchoCalc    endp
  632.  
  633.  
  634.  
  635. ;************************************************************************
  636. ;*        HardwareTicks (48 bit time to si:dx:ax in 838 ns units)
  637. ;************************************************************************
  638.  
  639. TimerResolution equ    1193            ; hw ticks per millisecond
  640.  
  641. InitTimer    proc    near
  642.         test    ArgFlags,TIM_NOHIRES
  643.         jnz    InitTimRet
  644.         mov    dx,043h         ; select timer control port
  645.         mov    al,034h
  646.         out    dx,al            ; mode 2: Rate generator
  647.         call    IoDelay         ;   (counts down by 1 to zero)
  648.         xor    ax,ax
  649.         mov    dx,040h         ; select timer 0
  650.         out    dx,al            ; set divide by 2**16
  651.         call    IoDelay
  652.         out    dx,al            ; the generator is now started
  653.   InitTimRet:
  654.         ret
  655. InitTimer    endp
  656.  
  657. RestoreTimer    proc    near
  658.         test    ArgFlags,TIM_NOHIRES
  659.         jnz    ResTimRet
  660.         mov    dx,043h         ; select timer control port
  661.         mov    al,036h
  662.         out    dx,al            ; mode 3: Square wave generator
  663.         call    IoDelay         ;   (counts down by 2 to zero,
  664.         xor    ax,ax            ;    twice)
  665.         mov    dx,040h         ; select timer 0
  666.         out    dx,al            ; set divide by 2**16
  667.         call    IoDelay
  668.         out    dx,al
  669.   ResTimRet:
  670.         ret
  671. RestoreTimer    endp
  672.  
  673. IoDelay     proc    near
  674.         push    ax
  675. ;*test        in    al,061h
  676.         pop    ax
  677.         ret
  678. IoDelay     endp
  679.  
  680. HardwareTicks    proc    near
  681.         push    es
  682.         PushfDI
  683.         test    ArgFlags,TIM_NOHIRES
  684.         jnz    HwTicksNoHi
  685.  
  686.         mov    dx,020h         ;/* Address PIC ocw3   */
  687.         mov    al,00Ah         ;/* Ask to read irr    */
  688.         out    dx,al
  689.  
  690.         xor    al,al            ;/* Latch timer 0 */
  691.         out    043h,al
  692.         in    al,040h         ;/* Counter --> ax*/
  693.         mov    ah,al            ;/* LSB in AH      */
  694.         in    al,040h         ;/* MSB in AL      */
  695.         xchg    al,ah   
  696.         not    ax            ;/* Need ascending counter */
  697.         push    ax            ; Save hardware counter value
  698.  
  699.         in    al,dx            ;/* Read irr      */
  700.         push    ax            ; Save irr
  701.  
  702.         in    al,021h         ;/* Read PIC imr  */
  703.         push    ax            ; Save imr
  704.  
  705.         mov    al,00FFh        ;/* Mask all interrupts */
  706.         out    021h,al
  707.  
  708.         mov    ax,040h         ;/* read low word of time */
  709.         mov    es,ax            ;/* from BIOS data area   */
  710.         mov    dx,es:[06Ch]
  711.         mov    si,es:[06Ch+2]        ; get high word too
  712.  
  713.         pop    ax            ; Restore imr
  714.         out    021h,al
  715.         pop    ax            ; Restore irr
  716.         test    al,001h         ;/* Counter hit 0?    */
  717.                 pop     ax                      ; Restore counter value
  718.                 jnz     HwTicksMore             ;/* Jump if yes       */
  719.         popfEI
  720.         pop     es
  721.                 ret
  722.  
  723.   HwTicksMore:
  724.                 cmp     ax,0FFh                 ;/* Counter > 0x0FF?    */
  725.         ja    HwTicksDone        ;/* Done if so          */
  726.  
  727.         inc    dx            ;/* Else count int req. */
  728.   HwTicksDone:
  729.         popfEI
  730.         pop    es
  731.         ret
  732.  
  733.   HwTicksNoHi:
  734.         mov    ax,040h         ;/* read low word of time */
  735.         mov    es,ax            ;/* from BIOS data area   */
  736.         mov    dx,es:[06Ch]
  737.         mov    si,es:[06Ch+2]
  738.         xor    ax,ax
  739.         popfEI
  740.         pop    es
  741.         ret
  742. HardwareTicks    endp
  743.  
  744.  
  745.  
  746. ;========================================================================
  747. ;        endinclude
  748.